/* === S T A R T =========================================================== */

#ifndef __SYNFIG_STUDIO_STATE_BONE_H
#define __SYNFIG_STUDIO_STATE_BONE_H

/* === H E A D E R S ======================================================= */

#ifdef USING_PCH
#	include "pch.h"
#else
#ifdef HAVE_CONFIG_H
#	include <config.h>
#endif

#include <gtkmm/dialog.h>
#include <gtkmm/entry.h>

#include <synfig/valuenode_dynamiclist.h>
#include <synfigapp/action_system.h>
#include <synfig/valuenode_bline.h>

#include "state_bone.h"
#include "canvasview.h"
#include "workarea.h"
#include "app.h"

#include <synfigapp/action.h>
#include "event_mouse.h"
#include "event_layerclick.h"
#include "toolbox.h"
#include "dialog_tooloptions.h"
#include <gtkmm/optionmenu.h>
#include "duck.h"
#include "widget_enum.h"
#include <synfigapp/main.h>

#include "general.h"

#endif


#include "smach.h"

#define dbg(MSG, ...) { printf("[IAKKO]: "); printf(MSG, ## __VA_ARGS__); printf("\n"); };

using namespace std;
using namespace etl;
using namespace synfig;
using namespace studio;

namespace studio {

	typedef std::list<synfig::Point> PointList;
	typedef std::list< etl::handle<Duck> > DuckList;

	// ###########################################################################
	// ### State Bone Context
	// ###########################################################################
	
	class ARTStateBoneContext : public sigc::trackable
	{
	public:
		ARTStateBoneContext(CanvasView* canvas_view);
		~ARTStateBoneContext();
	
	
	// ================================
	// Put members declaration below...
	// ================================
	private:
		etl::handle<CanvasView> canvas_view_;
		CanvasView::IsWorking is_working;
	
		Duckmatic::Push duckmatic_push;
	
		Point point_holder;
	
		etl::handle<Duck> point2_duck;

		bool prev_workarea_layer_status_;
	
	
		//Toolbox settings
		synfigapp::Settings & settings;
	
		//Toolbox display
		Gtk::Table options_table;
	
		Widget_Enum		enum_falloff;
		#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
			Widget_Enum		enum_blend;
		#endif	// BLEND_METHOD_IN_TOOL_OPTIONS
	
		/*
		Gtk::Adjustment	adj_feather;
		Gtk::Adjustment	adj_number_of_bline_points;
		Gtk::Adjustment	adj_bline_point_angle_offset;
		Gtk::SpinButton	spin_feather;
		Gtk::SpinButton	spin_number_of_bline_points;
		Gtk::SpinButton	spin_bline_point_angle_offset;
	
		Gtk::CheckButton checkbutton_invert;
		Gtk::CheckButton checkbutton_layer_bone;
		Gtk::CheckButton checkbutton_layer_region;
		Gtk::CheckButton checkbutton_layer_outline;
		Gtk::CheckButton checkbutton_layer_curve_gradient;
		Gtk::CheckButton checkbutton_layer_plant;
		Gtk::CheckButton checkbutton_layer_link_origins;
		*/
	
		Point m_rPointStart;
		Point m_rPointStop;
	
		PointList m_rPoints;
		DuckList m_rDucks;
		
		synfig::String m_strId;
		
		Gtk::Entry m_rEntryId; //what to name the layer
	public:
	
	protected:
	
	
	// ================================
	// Put methods declaration below...
	// ================================
	private:
		void refresh_ducks();
	
		void doPutPoint(Point p_rPoint);
		void doBone();
	
		bool onBoneDuckChange(const synfig::Point &point, std::list<synfig::Point>::iterator iter);
	
	public:
		synfig::String getId() const { return m_rEntryId.get_text(); }
		void setId (const synfig::String & p_strValue) { return m_rEntryId.set_text(p_strValue); }
		// this only counts the layers which use blines - they're the only
		// ones we link the origins for
		
		/*
		int layers_to_create()const
		{
			return
				get_layer_region_flag() +
				get_layer_outline_flag() +
				get_layer_curve_gradient_flag() +
				get_layer_plant_flag();
		}
		*/
	
		int get_falloff()const { return enum_falloff.get_value(); }
		void set_falloff(int x) { return enum_falloff.set_value(x); }
	
	#ifdef BLEND_METHOD_IN_TOOL_OPTIONS
		int get_blend()const { return enum_blend.get_value(); }
		void set_blend(int x) { return enum_blend.set_value(x); }
	#endif	// BLEND_METHOD_IN_TOOL_OPTIONS
	
		/*
		Real get_feather()const { return adj_feather.get_value(); }
		void set_feather(Real f) { adj_feather.set_value(f); }
	
		Real get_number_of_bline_points()const { return adj_number_of_bline_points.get_value(); }
		void set_number_of_bline_points(Real f) { adj_number_of_bline_points.set_value(f); }
	
		Real get_bline_point_angle_offset()const { return adj_bline_point_angle_offset.get_value(); }
		void set_bline_point_angle_offset(Real f) { adj_bline_point_angle_offset.set_value(f); }
	
		bool get_invert()const { return checkbutton_invert.get_active(); }
		void set_invert(bool i) { checkbutton_invert.set_active(i); }
	
		bool get_layer_bone_flag()const { return checkbutton_layer_bone.get_active(); }
		void set_layer_bone_flag(bool x) { return checkbutton_layer_bone.set_active(x); }
	
		bool get_layer_region_flag()const { return checkbutton_layer_region.get_active(); }
		void set_layer_region_flag(bool x) { return checkbutton_layer_region.set_active(x); }
	
		bool get_layer_outline_flag()const { return checkbutton_layer_outline.get_active(); }
		void set_layer_outline_flag(bool x) { return checkbutton_layer_outline.set_active(x); }
	
		bool get_layer_curve_gradient_flag()const { return checkbutton_layer_curve_gradient.get_active(); }
		void set_layer_curve_gradient_flag(bool x) { return checkbutton_layer_curve_gradient.set_active(x); }
	
		bool get_layer_plant_flag()const { return checkbutton_layer_plant.get_active(); }
		void set_layer_plant_flag(bool x) { return checkbutton_layer_plant.set_active(x); }
	
		bool get_layer_link_origins_flag()const { return checkbutton_layer_link_origins.get_active(); }
		void set_layer_link_origins_flag(bool x) { return checkbutton_layer_link_origins.set_active(x); }
		*/
	
		void refresh_tool_options(); //to refresh the toolbox
	
		//events
		Smach::event_result event_stop_handler(const Smach::event & x);
		Smach::event_result event_refresh_handler(const Smach::event & x);
		Smach::event_result event_mouse_click_handler(const Smach::event & x);
		Smach::event_result event_refresh_tool_options(const Smach::event & x);
		Smach::event_result event_layer_selection_changed_handler(const  Smach::event & x);
	
		//Canvas interaction
		const etl::handle<CanvasView> & get_canvas_view() const { return canvas_view_; }
		etl::handle<synfigapp::CanvasInterface> get_canvas_interface() const { return canvas_view_->canvas_interface(); }
		synfig::Canvas::Handle get_canvas() const { return canvas_view_->get_canvas(); }
		WorkArea * get_work_area() const { return canvas_view_->get_work_area(); }
	
		//Modifying settings etc.
		void loadSettings();
		void saveSettings();
		void reset();
		void increment_id();
		bool egress_on_selection_change;
	
		void make_bone(const Point& p1, const Point& p2);
		void run();

	
		void doGDA();
	protected:


	}; // END of class ARTStateBoneContext

	// ###########################################################################
	// ### State Bone
	// ###########################################################################

	class ARTStateBone : public Smach::state<ARTStateBoneContext>
	{
	public:
		ARTStateBone();
		~ARTStateBone();
	}; // END of class StateCircle
	
	extern ARTStateBone state_bone;
	
}; // END of namespace studio

#endif
